#include "mqtt_file_transfer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <jansson.h>
#include "connection/mqtt_client.h"

// 发送上下文
typedef struct {
    file_transfer_ctx_t *ctx;
    FILE *file;
    file_meta_t meta;
    int current_chunk;
    int retry_count;
} send_context_t;

// 发送元数据
static int send_metadata(send_context_t *sctx) {
    char topic[256];
    snprintf(topic, sizeof(topic), "%s/%s", TOPIC_FILE_META, sctx->meta.file_id);

    // 创建JSON消息
    char *json_fmt = "{\"type\":%d,\"file_id\":\"%s\",\"filename\":\"%s\","
                     "\"file_size\":%zu,\"chunk_size\":%zu,\"total_chunks\":%d}";

    size_t json_len = snprintf(NULL, 0, json_fmt, MSG_TYPE_META,
                               sctx->meta.file_id, sctx->meta.filename,
                               sctx->meta.file_size, sctx->meta.chunk_size,
                               sctx->meta.total_chunks);

    char *json_msg = malloc(json_len + 1);
    snprintf(json_msg, json_len + 1, json_fmt, MSG_TYPE_META,
             sctx->meta.file_id, sctx->meta.filename,
             sctx->meta.file_size, sctx->meta.chunk_size,
             sctx->meta.total_chunks);

    // 发送消息
    int result = neu_mqtt_client_publish(sctx->ctx->mqtt_client, 1, topic,
                                         (uint8_t *)json_msg, json_len,
                                         sctx, NULL);

    free(json_msg);
    return result;
}

// 发送数据块
static int send_chunk(send_context_t *sctx, int chunk_index) {
    // 读取文件数据
    size_t chunk_size = sctx->meta.chunk_size;
    if (chunk_index == sctx->meta.total_chunks - 1) {
        // 最后一个块可能小于chunk_size
        chunk_size = sctx->meta.file_size - (chunk_index * sctx->meta.chunk_size);
    }

    uint8_t *data = malloc(chunk_size);
    if (!data) {
        return -1;
    }

    fseek(sctx->file, chunk_index * sctx->meta.chunk_size, SEEK_SET);
    size_t read = fread(data, 1, chunk_size, sctx->file);
    if (read != chunk_size) {
        free(data);
        return -1;
    }

    // Base64编码数据
    char *encoded_data = base64_encode(data, chunk_size);
    free(data);
    if (!encoded_data) {
        return -1;
    }

    // 创建主题
    char topic[256];
    snprintf(topic, sizeof(topic), "%s/%s", TOPIC_FILE_DATA, sctx->meta.file_id);

    // 创建JSON消息
    char *json_fmt = "{\"type\":%d,\"file_id\":\"%s\",\"chunk_index\":%d,"
                     "\"chunk_size\":%zu,\"data\":\"%s\"}";

    size_t json_len = snprintf(NULL, 0, json_fmt, MSG_TYPE_DATA,
                               sctx->meta.file_id, chunk_index,
                               chunk_size, encoded_data);

    char *json_msg = malloc(json_len + 1);
    snprintf(json_msg, json_len + 1, json_fmt, MSG_TYPE_DATA,
             sctx->meta.file_id, chunk_index,
             chunk_size, encoded_data);

    free(encoded_data);

    // 发送消息
    int result = neu_mqtt_client_publish(sctx->ctx->mqtt_client, 1, topic,
                                         (uint8_t *)json_msg, json_len,
                                         sctx, NULL);

    free(json_msg);
    return result;
}
// 修改后的ACK处理回调
static void ack_callback(neu_mqtt_qos_e qos, const char *topic,
                        const uint8_t *payload, uint32_t len, void *user_data) {
    send_context_t *sctx = (send_context_t *)user_data;
    (void)qos;
    (void)topic;
    // 解析ACK消息
    char *msg = malloc(len + 1);
    memcpy(msg, payload, len);
    msg[len] = '\0';

    json_error_t error;
    json_t *root = json_loads(msg, 0, &error);
    free(msg);

    if (!root) {
        printf("Failed to parse ACK JSON: %s\n", error.text);
        return ;
    }

    // 解析ACK字段
    json_t *file_id_obj = json_object_get(root, "file_id");
    json_t *chunk_index_obj = json_object_get(root, "chunk_index");
    json_t *status_obj = json_object_get(root, "status");

    if (!file_id_obj || !json_is_string(file_id_obj) ||
        !chunk_index_obj || !json_is_integer(chunk_index_obj) ||
        !status_obj || !json_is_integer(status_obj)) {
        printf("Invalid ACK format\n");
        json_decref(root);
        return ;
    }

    // 检查文件ID是否匹配
    const char *file_id = json_string_value(file_id_obj);
    if (strcmp(file_id, sctx->meta.file_id) != 0) {
        printf("File ID mismatch in ACK: expected %s, got %s\n", sctx->meta.file_id, file_id);
        json_decref(root);
        return ;
    }

    int chunk_index = json_integer_value(chunk_index_obj);
    int status = json_integer_value(status_obj);
    json_decref(root);

    if (status != 0) {
        // ACK状态非0，表示出错
        printf("ACK error for chunk %d: %d\n", chunk_index, status);

        if (sctx->retry_count < DEFAULT_MAX_RETRIES) {
            sctx->retry_count++;
            // 重试当前块
            send_chunk(sctx, sctx->current_chunk);
        } else {
            // 超过最大重试次数，失败
            if (sctx->ctx->complete_cb) {
                sctx->ctx->complete_cb(sctx->meta.file_id, -1, "Send failed after retries");
            }
            fclose(sctx->file);
            free(sctx);
        }
        return ;
    }

    // ACK成功
    printf("ACK received for chunk %d\n", chunk_index);
    sctx->retry_count = 0;
    sctx->current_chunk++;

    if (sctx->ctx->progress_cb) {
        sctx->ctx->progress_cb(sctx->meta.file_id, sctx->current_chunk, sctx->meta.total_chunks);
    }

    if (sctx->current_chunk < sctx->meta.total_chunks) {
        // 发送下一个块
        send_chunk(sctx, sctx->current_chunk);
    } else {
        // 传输完成
        if (sctx->ctx->complete_cb) {
            sctx->ctx->complete_cb(sctx->meta.file_id, 0, "Send completed");
        }
        fclose(sctx->file);
        free(sctx);
    }

    return ;
}
// ACK处理回调
// static void ack_callback(int result, neu_mqtt_qos_e qos, char *topic,
//                          uint8_t *payload, uint32_t len, void *user_data) {
//     send_context_t *sctx = (send_context_t *)user_data;
//     (void)qos;
//     (void)topic;
//     if (result != 0) {
//         // 发送失败
//         if (sctx->retry_count < DEFAULT_MAX_RETRIES) {
//             sctx->retry_count++;
//             // 重试当前块
//             send_chunk(sctx, sctx->current_chunk);
//         } else {
//             // 超过最大重试次数，失败
//             if (sctx->ctx->complete_cb) {
//                 sctx->ctx->complete_cb(sctx->meta.file_id, -1, "Send failed after retries");
//             }
//             fclose(sctx->file);
//             free(sctx);
//         }
//         return;
//     }

//     // 解析ACK消息
//     if (len > 0) {
//         char *msg = malloc(len + 1);
//         memcpy(msg, payload, len);
//         msg[len] = '\0';

//         // 这里简化处理，实际应该解析JSON确认消息
//         if (strstr(msg, "\"status\":0")) {
//             // ACK成功
//             sctx->retry_count = 0;
//             sctx->current_chunk++;

//             if (sctx->ctx->progress_cb) {
//                 sctx->ctx->progress_cb(sctx->meta.file_id, sctx->current_chunk, sctx->meta.total_chunks);
//             }

//             if (sctx->current_chunk < sctx->meta.total_chunks) {
//                 // 发送下一个块
//                 send_chunk(sctx, sctx->current_chunk);
//             } else {
//                 // 传输完成
//                 if (sctx->ctx->complete_cb) {
//                     sctx->ctx->complete_cb(sctx->meta.file_id, 0, "Send completed");
//                 }
//                 fclose(sctx->file);
//                 free(sctx);
//             }
//         } else {
//             // ACK失败
//             if (sctx->retry_count < DEFAULT_MAX_RETRIES) {
//                 sctx->retry_count++;
//                 // 重试当前块
//                 send_chunk(sctx, sctx->current_chunk);
//             } else {
//                 // 超过最大重试次数，失败
//                 if (sctx->ctx->complete_cb) {
//                     sctx->ctx->complete_cb(sctx->meta.file_id, -1, "Send failed after retries");
//                 }
//                 fclose(sctx->file);
//                 free(sctx);
//             }
//         }

//         free(msg);
//     }
// }

// 订阅ACK主题
static int subscribe_ack(send_context_t *sctx) {
    char topic[256];
    snprintf(topic, sizeof(topic), "%s/%s", TOPIC_FILE_ACK, sctx->meta.file_id);

    return neu_mqtt_client_subscribe(sctx->ctx->mqtt_client, 1, topic,
                                     sctx, ack_callback);
}

// 发送文件
int file_transfer_send(file_transfer_ctx_t *ctx, const char *filename) {
    // 检查文件是否存在
    if (access(filename, F_OK) != 0) {
        return -1;
    }

    // 创建发送上下文
    send_context_t *sctx = malloc(sizeof(send_context_t));
    if (!sctx) {
        return -1;
    }

    sctx->ctx = ctx;
    sctx->current_chunk = 0;
    sctx->retry_count = 0;

    // 打开文件
    sctx->file = fopen(filename, "rb");
    if (!sctx->file) {
        free(sctx);
        return -1;
    }

    // 设置元数据
    strncpy(sctx->meta.file_id, generate_file_id(), sizeof(sctx->meta.file_id));
    strncpy(sctx->meta.filename, filename, sizeof(sctx->meta.filename));
    sctx->meta.file_size = get_file_size(filename);
    sctx->meta.chunk_size = ctx->chunk_size;
    sctx->meta.total_chunks = (sctx->meta.file_size + ctx->chunk_size - 1) / ctx->chunk_size;

    // 订阅ACK主题
    if (subscribe_ack(sctx) != 0) {
        fclose(sctx->file);
        free(sctx);
        return -1;
    }

    // 发送元数据
    if (send_metadata(sctx) != 0) {
        fclose(sctx->file);
        free(sctx);
        return -1;
    }

    return 0;
}
